本篇大綱:DOM 元素、SVG 重點概述、SVG 形狀/線條/路徑/文字、SVG樣式
上一章有提過在學習D3之前需要具備的知識,這邊就來講解其中最重要的一點:SVG!由於 D3.js 的畫面渲染部分是用 SVG 運作,因此如果完全不懂 SVG 的話,就無法順利使用 D3 了~現在來說說 SVG 是什麼吧!
在講SVG之前,我們需要先了解 html DOM樹 的概念。為什麼得要先了解DOM呢? 主要是因為 D3 是靠著操作 DOM 元素來進行node節點增減,再透過 SVG 去渲染圖表
。
DOM 的全名是 Document Object Model,中文叫做文件物件模型。聽起來好像很複雜抽象,但其實就是把 HTML 文件中的每個標籤都定義成物件,最後這些物件會形成像是樹狀的結構。像下圖就是一個基本的html文件樹狀圖:
所以如果你的程式碼長這樣
<div>
<div class="box">
<div class="box1"></div>
<div class="box2"></div>
</div>
<div class="list">
<ul>
<li></li>
<li></li>
<li></li>
</ul>
</div>
</div>
你的 DOM 樹結構就會是這樣
這裡的每一個 html 標籤就視為一個 node 節點,D3 是將數據資料綁定到節點,並增減節點來建立圖表。
有了以上的 DOM 概念後,我們就可以來看SVG啦!SVG 的全名是 Scale Vector Graphics (可縮放向量圖型),是以** XML 文字檔來建立 2D 的向量圖形**,因此開發者可以直接在 HTML 檔案中使用 SVG,而且也支援動畫跟互動的操作。
SVG 圖形可以有不同的形式
D3.js使用的就是第二種形式,在 html 檔案中使用svg標籤,並宣告它的空間範圍。接著在這個範圍內放入要繪製的圖形元素標籤,以及它的位置、顏色等等相關資訊
<svg width="500" height="500">
這邊放入要繪製的圖形元素標籤...
</svg>
了解SVG之後,我們來看一下SVG的一些基本概念
SVG 是基於 XML 文字檔格式,產生DOM樹
(不像canvas是平面畫布)
SVG 定義了一系列圖形元素
,例如「圓或矩形等基本形狀、文字、直線、曲線」等等,然後再透過外觀屬性去改變這些形狀的尺寸、位置、顏色等等
。
例如:svg 定義的 < rect > 矩形元素,< rect > 透過外觀屬形 x, y 去控制圖形位置;width, height 控制圖形大小;style 則控制邊框、顏色
<svg width="400" height="200" style="border:1px solid red">
<rect x="20" y="20" width="300" height="100"
style="fill:rgb(255, 0, 255); stroke-width:3; stroke:rgb(0,0,0)" />
</svg>
結構元素
,例如: < svg >、 < g >、< use >
。大家在看別人的 svg 程式碼時,應該蠻常看到下圖 這個元素,它就是其中一種 SVG 的結構元素那你可能就會問,什麼是結構元素呢?結構元素是一種容器元素,不會繪製外型,而是用來包裹多個子元素
,這樣一來就能將其下的子元素包成一個大包的共同元素,統一去改變位置、形狀或顏色等等。
我們可以簡單整理一下結構元素的特點:
後來寫的元素會遮蓋掉先前出現的元素
原點是左上角
,由上而下、從左至右回應事件進行互動
原則上是無限大
,width / height 只是定義 viewport (可視範圍)。但是不可能所有數據都剛好符合我們設定的視窗比例,這也正是為什麼、要定義比例尺的原因。透過比例尺去定義出視窗大小跟數據的比例,才能將繪製完的圖形完整放到我們的 svg 視窗內。
看完這些之後,相信大家對 SVG 已經有概念了。接下來我們來看看 SVG 定義的一些形狀、線條、路徑,以及它們的屬性吧!
svg 已經先幫我們定義好一些形狀,並賦予相對應的標籤。我們只要使用這些標籤,並添加固定的屬性,就可以畫出一些基本的形狀啦~這些定義好的形狀包含:
< rect > 矩形
屬性 | 意義 |
---|---|
x, y | 左上角座標寬、高 |
width, height | 寬高 |
rx, ry | 水平/垂直邊角半徑 |
範例:從坐標軸 x 20 與 y 20 的地方開始,建立一個寬300、高100的長方形;內部填滿桃紅色,並且要有3px的粗黑邊框
<svg width="400" height="200" style="border:1px solid red">
<rect x="20" y="20" width="300" height="100"
style="fill:rgb(255, 0, 255); stroke-width:3; stroke:rgb(0,0,0)" />
</svg>
< circle > 圓形
屬性 | 意義 |
---|---|
cx, cy | 水平/垂直中心座標 |
r | 半徑 |
範例:從坐標軸 x 100 與 y 50 的地方開始,建立一個半徑為40的圓型,內部填滿紅色,且要有3px的粗黑邊框
<svg width="400" height="150" style="border:1px solid red">
<circle cx="100" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>
< ellipse > 橢圓形
屬性 | 意義 |
---|---|
cx, cy | 中心座標水平 |
rx, ry | 垂直半徑 |
範例:從坐標軸 x 200 與 y 80 的地方開始,建立一個x半徑為80、y半徑為50的橢圓型,內部填滿淡粉紅色,且要有3px的粗黑邊框
<svg width="400" height="150">
<ellipse cx="200" cy="80" rx="80" ry="50" stroke="black" stroke-width="3" fill="pink"></ellipse>
</svg>
< line > 線條
屬性 | 意義 |
---|---|
x1, x2 | 座標開始點 |
y1, y2 | 座標結束點 |
範例:繪製第一端在圓點( x0, y0 ),另外一端在( x200, y200 )的直線,粗度為2px
<svg width="400" height="200">
<line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(0,0,255); stroke-width:2" />
</svg>
< polyline > 折線
屬性 | 意義 |
---|---|
points | 表示每個點之間的 X、Y 座標 |
範例:繪製端點 20,50 40,25 60,40 80,120 120,140 160,180 的折線,粗度為3px
<svg width="400" height="200">
<polyline
points="20,50 40,25 60,40 80,120 120,140 160,180 "
style="fill: none; stroke: orangered; stroke-width: 3"
/>
</svg>
< polygon > 多邊形
屬性 | 意義 |
---|---|
points | 表示每個點之間的 X、Y 座標 |
範例:繪製端點 200,10 250,190 160,180 的閉合形狀,顏色填滿為綠色,邊框粗度為3px
<svg width="400" height="200">
<polygon
points="200,10 250,190 160,180"
style="fill: lime; stroke: purple; stroke-width: 1"
/>
</svg>
< path > 路徑
屬性 | 意義 |
---|---|
d | 路徑 |
< path > 元素是在 SVG 中最常見的指令,它可以透過命令語言繪製任何形狀。它只有一個 d 屬性,而屬性值是由「空白間隔的命令」+「座標字串」組合而成。
所有的「空白間隔的命令」都是用一個英文字元指令,並具備兩種形式
習慣上在一開始時,會用 M 命令移動到一個明確的位置再開始繪製。至於座標的部分,在 < path > 中的座標都沒有單位,而且可以有負值。
以下列出幾個常見的命令英文代號,但由於繪製路徑很複雜,一般我們不會自己算座標去畫圖,而是使用一些輔助工具 (例如 AI illustrator) 畫好圖片後存成SVG檔,而D3.js 也提供了函式去產生相對應的路徑。
命令英文代號
M, m
移動至特定位置 (不會繪製線條)L, l
畫一條直線到...H, h
水平線V, v
垂直線Z, z
把目前座標的點跟第一點連起來,並形成封閉路徑C, c
立方貝茲曲線S, s
從多個控制點畫立方貝茲曲線Q, q
畫貝茲曲線T, t
從多個控制點畫貝茲曲線A, a
從目前的位置畫橢圓曲線<svg width="400" height="200">
<path
d="M50 20 C80 90,40 200,250,100"
stroke="black"
fill="none"
stroke-width="2"
/>
</svg>
也可以透過不同線段畫出有趣的圖
<svg width="100" height="100">
<path
d="M25,15 L25,30
M75,15 L75,30
M15,50 C20,80 80,80 85,50"
stroke="black"
fill="none"
stroke-width="2"
/>
</svg>
< text > 文字
屬性 | 意義 |
---|---|
x,y | 文字的座標 |
dx | 以 x 座標為基準,平行移動文字距離(正為往右,負為往左)。 |
dy | 以 Y 座標為基準,垂直移動文字距離(正為往上,負為往下)。 |
textLength | 設定這段文字的長度,和 lengthAdjust ( 設定對這段文字長度的調整 ) 搭配運作 |
text-anchor | 文字開始繪製位置 (靠左、置中、靠右對齊) |
rotate | 每個文字的旋轉角度,若是要整組文字一起旋轉可以使用 transform="rotate()" |
特別的是,只要把屬形值改為陣列 [ ] ,這些屬性就可以針對單一字元設定。
<svg width="400" height="200">
<text x="50,60,80" y="80,120,40" fill="blue" text-anchor="start">
SVG 真有趣!
</text>
</svg>
看完上述SVG定義的圖形後,會發現這些標籤還跟著很多屬性的設定。有了這些屬性,我們才能設定形狀的樣式、動畫等等,以下就來介紹一些常見的屬性:
常用表現屬性:
常用表現屬性 | 用途 |
---|---|
< stroke > |
圖形的邊框顏色 |
< stroke-width > |
圖形的邊框粗細 |
< fill > |
圖形的內部填滿顏色 |
< font-size > |
文字尺寸 |
< opacity > |
圖形的透明度 |
< visibility > |
圖形是否可視 |
.
轉換屬性:移動、旋轉、延展、推移
常用轉換屬性 | 用途 |
---|---|
< rotate > |
圖形旋轉 |
< transform > |
圖形變形 |
.
如果看完這邊後,想再更深入了解SVG的話,可以參考 W3C的SVG教學 ,裡面根據每個SVG的圖形跟樣式都有個別說明~
關於SVG的屬性,我這邊只介紹一些比較常用的~如果想看完整的屬性列表,則可以到MDN的頁面查找
.
最後,這邊附上本章的程式碼與圖表 Github 、 Github Page,需要的人請自行取用~
今天終於平安的結束啦~明天再見!